package com.wjw.java.basic.operator_;

/**-------------------------------------------------------
 * 基础知识：需要知道二进制,ConvertBinary.class中有详解
 * -------------------------------------------------------
 * 原码、反码、补码
 * 1.二进制的最高位(最左边)是符号位：0表示正数,1表示负数(口诀：0->0   1->-)
 * 2.正数的原码、反码、补码都一样
 * 3.负数的反码 = 它的原码符号位不变,其他位取反(0->1 , 1->0)
 * 4.负数的补码 = 它的反码 + 1
 *   负数的反码 = 它的补码 - 1
 *   负数的原码 = 反码符号位不变,其他位取反(0->1 , 1->0)
 * 5.0的反码、补码都是0
 * 6.java没有无符号数,即：java中的数都是有符号的
 * 7.在计算机运算的时候,都是以"补码的方式来运算"的
 * 8.当我们看运算结果的时候,要看他的原码(重点)
 * -------------------------------------------------------
 * java中有7个位运算符：
 * -------------------------------------------------------
 * 按位与&：两位全为1,结果为1,否则为0
 * 按位或|：两位有一个为1,结果为1,否则为0
 * 按位异或^：两位一个为0,一个为1(两个不一样),结果为1,否则为0
 * 按位取反~：0 -> 1, 1 -> 0
 *
 * 高位左边,低位右边
 * 算术右移>>：低位溢出,符号位不变,并用符号位补溢出的高位
 *            移动一位就得除以2,移动两位得除以2个2...以此类推
 * 算术左移<<：符号位不变,低位补0
 *            移动一位就得乘以2,移动两位得乘以2个2...以此类推
 * 逻辑右移(无符号右移)>>>：低位溢出,高位补0
 * -------------------------------------------------------
 *      1001 0001
 *      1010 0101
 *
 * &    1001 0001
 * |    1011 0101
 * ^    0011 0100
 *
 * 1>>2：1/2/2 = 0
 * 1>>3：1/2/2/2 = 0
 * 1<<2：1*2*2 = 4
 * 1<<3：1*2*2*2 = 8
 * -------------------------------------------------------
 */
public class OperatorBitwise {
    public static void main(String[] args) {
        anwei_yu();//按位与             &
        anwei_huo();//按位或            |
        anwei_yihuo();//按位异或        ^
        anwei_qufan();//按位取反(简单)   ~
        anwei_qufan2();//按位取反(复杂)  ~

        System.out.println("-----------------------------");

        suanshu_youyi();//算术右移
        suanshu_zuoyi();//算术左移

    }

    /**
     * 1.按位与：&
     */
    public static void anwei_yu(){
        /**
         * 推到过程：运算看补码、结果看原码
         * ----------------------------------------------------------------
         * 2是int类型,占4个byte(字节),32bit(位)
         * 2的原码为：00000000 00000000 00000000 00000010
         * 最高位0开头,所以是正数,原码、反码、补码都一样
         * 运算时看补码,所以2的补码为：00000000 00000000 00000000 00000010
         * ----------------------------------------------------------------
         * 3是int类型,占4个byte(字节),32bit(位)
         * 3的原码为：00000000 00000000 00000000 00000011
         * 最高位0开头,所以是正数,原码、反码、补码都是一样的
         * 运算时看补码,所以3的补码为：00000000 00000000 00000000 00000011
         * ----------------------------------------------------------------
         * 2的补码为：00000000 00000000 00000000 00000010
         * 3的补码为：00000000 00000000 00000000 00000011
         * 【按位与&：两位全为1,结果为1,否则为0】
         * 2&3的补码：00000000 00000000 00000000 00000010
         * 因为2&3运算后补码的最高位为：0,是正数,所以原码如下
         * 2&3的原码：00000000 00000000 00000000 00000010
         * 2&3转为十进制结果为：2
         * ----------------------------------------------------------------
         */
        System.out.println("2&3的结果是："+(2&3));//2
    }

    /**
     * 2.按位或：|
     */
    public static void anwei_huo(){
        /**
         * 推到过程：运算看补码、结果看原码
         * ----------------------------------------------------------------
         * 2是int类型,占4个byte(字节),32bit(位)
         * 2的原码为：00000000 00000000 00000000 00000010
         * 最高位0开头,所以是正数,原码、反码、补码都一样
         * 运算时看补码,所以2的补码为：00000000 00000000 00000000 00000010
         * ----------------------------------------------------------------
         * 3是int类型,占4个byte(字节),32bit(位)
         * 3的原码为：00000000 00000000 00000000 00000011
         * 最高位0开头,所以是正数,原码、反码、补码都是一样的
         * 运算时看补码,所以3的补码为：00000000 00000000 00000000 00000011
         * ----------------------------------------------------------------
         * 2的补码为：00000000 00000000 00000000 00000010
         * 3的补码为：00000000 00000000 00000000 00000011
         * 【按位或|：两位有一个为1,结果为1,否则为0】
         * 2|3的补码：00000000 00000000 00000000 00000011
         * 因为2|3运算后补码的最高位为：0,是正数,所以原码如下
         * 2|3的原码：00000000 00000000 00000000 00000011
         * 2|3转为十进制结果为：3
         * ----------------------------------------------------------------
         */
        System.out.println("2|3的结果是："+(2|3));//3
    }

    /**
     * 3.按位或：^
     */
    public static void anwei_yihuo(){
        /**
         * 推到过程：运算看补码、结果看原码
         * ----------------------------------------------------------------
         * 2是int类型,占4个byte(字节),32bit(位)
         * 2的原码为：00000000 00000000 00000000 00000010
         * 最高位0开头,所以是正数,原码、反码、补码都一样
         * 运算时看补码,所以2的补码为：00000000 00000000 00000000 00000010
         * ----------------------------------------------------------------
         * 3是int类型,占4个byte(字节),32bit(位)
         * 3的原码为：00000000 00000000 00000000 00000011
         * 最高位0开头,所以是正数,原码、反码、补码都是一样的
         * 运算时看补码,所以3的补码为：00000000 00000000 00000000 00000011
         * ----------------------------------------------------------------
         * 2的补码为：00000000 00000000 00000000 00000010
         * 3的补码为：00000000 00000000 00000000 00000011
         * 【两位一个为0,一个为1(两个不一样),结果为1,否则为0】
         * 2^3的补码：00000000 00000000 00000000 00000001
         * 因为2^3运算后补码的最高位为：0,是正数,所以原码如下
         * 2^3的原码：00000000 00000000 00000000 00000001
         * 2^3转为十进制结果为：1
         * ----------------------------------------------------------------
         */
        System.out.println("2^3的结果是："+(2^3));//1
    }

    /**
     * 4.1按位取反(简单)：~
     */
    public static void anwei_qufan(){
        /**
         * 推到过程：运算看补码、结果看原码
         * ----------------------------------------------------------------
         * -2是int类型,占4个byte(字节),32bit(位)
         * -2的原码为：10000000 00000000 00000000 00000010
         * 最高位1开头,所以是负数,
         * 数的反码 = 它的原码符号位不变,其他位取反(0->1 , 1->0),
         * -2的反码为：11111111 11111111 11111111 11111101
         * 负数的补码 = 它的反码 + 1
         * -2的补码为：11111111 11111111 11111111 11111110
         * 【按位取反~：0 -> 1, 1 -> 0】
         * ~-2的补码为：00000000 00000000 00000000 00000001
         * 因为~-2运算后补码的最高位为：0,是正数,所以原码如下
         * ~-2的原码为：00000000 00000000 00000000 00000001
         * ~-2转为十进制结果为：1
         * ----------------------------------------------------------------
         */
        System.out.println("~-2的结果是："+(~-2));//1
    }
    /**
     * 4.2按位取反(复杂)：~
     */
    public static void anwei_qufan2(){
        /**
         * 推到过程：运算看补码、结果看原码
         * ----------------------------------------------------------------
         * 2是int类型,占4个byte(字节),32bit(位)
         * 2的原码为：00000000 00000000 00000000 00000010
         * 最高位0开头,所以是正数,原码、反码、补码都一样
         * 2的反码为：00000000 00000000 00000000 00000010
         * 2的补码为：00000000 00000000 00000000 00000010
         * 【按位取反~：0 -> 1, 1 -> 0】
         * ~2的补码为：11111111 11111111 11111111 11111101
         * 因为~-2运算后补码的最高位为：1,是负数,所以原码如下
         * 负数的反码 = 它的补码 - 1
         * ~2的反码为：11111111 11111111 11111111 11111100
         * 数的原码 = 反码符号位不变,其他位取反(0->1 , 1->0)
         * ~2的原码为：10000000 00000000 00000000 00000011
         * ~2转为十进制结果为：-3
         * ----------------------------------------------------------------
         */
        System.out.println("~2的结果是："+(~2));//-3
    }

    /**
     * 5.算术右移：>>
     */
    public static void suanshu_youyi(){
        /**
         * 口诀：低位溢出,符号位不变,并用符号位补溢出的高位
         * ----------------------------------------------------------------
         * 1是int类型,占4byte(字节),32bit(位)
         * 二进制数为：00000000 00000000 00000000 00000001
         * 1>>2,是将最右边的最后两位01,向右移动2位,会溢出
         *            00000000 00000000 00000000 00000000 01(溢出了,因为只有32位,溢出了两位,用符号位用0补溢出的2位)
         * 1>>2结果是：00000000 00000000 00000000 00000000
         * 1>>2：相当于1/2/2 = 0
         * 1>>2的十进制就是：0
         */
        System.out.println("1>>2的结果是："+(1>>2));//0
    }

    /**
     * 6.算术左移: <<
     */
    public static void suanshu_zuoyi(){
        /**
         * 口诀：符号位不变,低位补0
         * ----------------------------------------------------------------
         * 1是int类型,占4byte(字节),32bit(位)
         * 二进制数为：00000000 00000000 00000000 00000001
         * 1<<2,是将最右边的最后两位01,向左移动2位
         *            00000000 00000000 00000000 00000100 (01向左移动2位后,低位用0补充)
         * 1<<2结果是：00000000 00000000 00000000 00000100
         * 1<<2：相当于1*2*2 = 4
         * 1<<2的十进制就是：4
         */
        System.out.println("1<<2的结果是："+(1<<2));//4
    }

    /**
     * 7.逻辑右移：>>>
     */
    public static void luoji_youyi(){
        /**
         * 口诀：逻辑右移(无符号右移)>>>：低位溢出,高位补0
         * ----------------------------------------------------------------
         */
    }
}
